package com.xiaoer.river.define.mapping;

import cn.hutool.core.lang.ClassScanner;
import cn.hutool.core.util.ReflectUtil;
import com.xiaoer.river.define.annotation.RiverAround;
import com.xiaoer.river.define.annotation.RiverNode;
import com.xiaoer.river.define.annotation.RiverService;
import com.xiaoer.river.define.api.NodeAround;
import com.xiaoer.river.define.entity.NodeMethod;

import java.lang.reflect.Method;
import java.util.Set;

/**
 * 节点扫描器
 *
 * @author yinxiuhe
 * @date 2021/3/25 16:26
 */
public class NodeScanner {

    /**
     * 扫描节点
     *
     * @param packagePath 包路径
     * @return 节点映射
     */
    public static NodeMapping scan(String packagePath) {
        NodeMapping nodeMapping = new NodeMapping();
        Set<Class<?>> classes = ClassScanner.scanPackage(packagePath);
        classes.parallelStream().forEach(clazz -> {
            if (clazz.isAnnotationPresent(RiverService.class)) {
                Object service = ReflectUtil.newInstance(clazz);
                Method[] methods = ReflectUtil.getMethods(clazz);
                //将流程服务中包含RiverNode注解的方法放入节点映射对象中
                for (Method method : methods) {
                    if (method.isAnnotationPresent(RiverNode.class)) {
                        RiverNode annotation = method.getAnnotation(RiverNode.class);
                        NodeMethod nodeMethod = new NodeMethod(annotation.value(), annotation.name(), service, method);
                        nodeMapping.put(annotation.value(), nodeMethod);
                    }
                }
            } else if (NodeAround.class.isAssignableFrom(clazz) && !NodeAround.class.equals(clazz)
                    && clazz.isAnnotationPresent(RiverAround.class)) {
                RiverAround annotation = clazz.getAnnotation(RiverAround.class);
                NodeAround nodeAround = (NodeAround) ReflectUtil.newInstance(clazz);
                nodeMapping.putAround(annotation.value(), nodeAround);
            }
        });
        return nodeMapping;
    }

}
